home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / Synthesizer Source / Synthesizer Folder / AlgoWaveTableObject.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  30.7 KB  |  1,016 lines  |  [TEXT/KAHL]

  1. /* AlgoWaveTableObject.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Synthesizer:  Digital Music Synthesis on General Purpose Computers     */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "AlgoWaveTableObject.h"
  31. #include "AlgoWaveTableList.h"
  32. #include "Memory.h"
  33. #include "DataMunging.h"
  34. #include "CodeCenter.h"
  35. #include "PcodeStack.h"
  36. #include "PcodeSystem.h"
  37. #include "FixedPoint.h"
  38. #include "MainWindowStuff.h"
  39. #include "Alert.h"
  40. #include "Numbers.h"
  41. #include "AlgoWaveTableWindow.h"
  42. #include "WaveTableStorage.h"
  43. #include "CompilerRoot.h"
  44. #include "FunctionCode.h"
  45. #include "BufferedFileInput.h"
  46. #include "BufferedFileOutput.h"
  47.  
  48.  
  49. struct AlgoWaveTableObjectRec
  50.     {
  51.         MyBoolean                                DataModified;
  52.  
  53.         char*                                        Name;
  54.         char*                                        AlgoWaveTableFormula;
  55.  
  56.         MyBoolean                                NeedsToBeRebuilt;
  57.         WaveTableStorageRec*        WaveTableData; /* NIL if not built */
  58.         NumBitsType                            NumBits;
  59.         long                                        NumFrames;
  60.         long                                        NumTables;
  61.  
  62.         AlgoWaveTableWindowRec*    AlgoWaveTableWindow;
  63.  
  64.         struct CodeCenterRec*        CodeCenter;
  65.         struct MainWindowRec*        MainWindow;
  66.         AlgoWaveTableListRec*        AlgoWaveTableList;
  67.  
  68.         short                                        SavedWindowXLoc;
  69.         short                                        SavedWindowYLoc;
  70.         short                                        SavedWindowWidth;
  71.         short                                        SavedWindowHeight;
  72.     };
  73.  
  74.  
  75. /* allocate and create a new algorithmic wave table */
  76. AlgoWaveTableObjectRec*    NewAlgoWaveTableObject(struct CodeCenterRec* CodeCenter,
  77.                                                 struct MainWindowRec* MainWindow,
  78.                                                 struct AlgoWaveTableListRec* AlgoWaveTableList)
  79.     {
  80.         AlgoWaveTableObjectRec*    AlgoWaveTableObj;
  81.  
  82.         AlgoWaveTableObj = (AlgoWaveTableObjectRec*)AllocPtrCanFail(
  83.             sizeof(AlgoWaveTableObjectRec),"AlgoWaveTableObjectRec");
  84.         if (AlgoWaveTableObj == NIL)
  85.             {
  86.              FailurePoint1:
  87.                 return AlgoWaveTableObj;
  88.             }
  89.         AlgoWaveTableObj->Name = StringToBlockCopy("untitled");
  90.         if (AlgoWaveTableObj->Name == NIL)
  91.             {
  92.              FailurePoint2:
  93.                 ReleasePtr((char*)AlgoWaveTableObj);
  94.                 goto FailurePoint1;
  95.             }
  96.         AlgoWaveTableObj->AlgoWaveTableFormula = StringToBlockCopy(
  97.             "# frames : integer; tables : integer; data : fixedarray\x0a");
  98.         if (AlgoWaveTableObj->AlgoWaveTableFormula == NIL)
  99.             {
  100.              FailurePoint3:
  101.                 ReleasePtr(AlgoWaveTableObj->Name);
  102.                 goto FailurePoint2;
  103.             }
  104.         AlgoWaveTableObj->DataModified = False;
  105.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  106.         AlgoWaveTableObj->WaveTableData = NIL;
  107.         AlgoWaveTableObj->NumBits = eSample16bit;
  108.         AlgoWaveTableObj->NumFrames = 256;
  109.         AlgoWaveTableObj->NumTables = 256;
  110.         AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
  111.         AlgoWaveTableObj->CodeCenter = CodeCenter;
  112.         AlgoWaveTableObj->MainWindow = MainWindow;
  113.         AlgoWaveTableObj->AlgoWaveTableList = AlgoWaveTableList;
  114.         AlgoWaveTableObj->SavedWindowXLoc = 0;
  115.         AlgoWaveTableObj->SavedWindowYLoc = 0;
  116.         AlgoWaveTableObj->SavedWindowWidth = 0;
  117.         AlgoWaveTableObj->SavedWindowHeight = 0;
  118.         return AlgoWaveTableObj;
  119.     }
  120.  
  121.  
  122. /* dispose of all data structures associated with wave table */
  123. void                                    DisposeAlgoWaveTableObject(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  124.     {
  125.         CheckPtrExistence(AlgoWaveTableObj);
  126.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  127.             {
  128.                 DisposeAlgoWaveTableWindow(AlgoWaveTableObj->AlgoWaveTableWindow);
  129.                 ERROR(AlgoWaveTableObj->AlgoWaveTableWindow != NIL,PRERR(ForceAbort,
  130.                     "DisposeAlgoWaveTableObject: window thing not NIL after disposing"));
  131.             }
  132.         ReleasePtr(AlgoWaveTableObj->Name);
  133.         ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  134.         if (AlgoWaveTableObj->WaveTableData != NIL)
  135.             {
  136.                 DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  137.             }
  138.         ReleasePtr((char*)AlgoWaveTableObj);
  139.     }
  140.  
  141.  
  142. /* find out if any changes have been made to it */
  143. MyBoolean                            HasAlgoWaveTableObjectBeenModified(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  144.     {
  145.         CheckPtrExistence(AlgoWaveTableObj);
  146.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  147.             {
  148.                 return AlgoWaveTableObj->DataModified
  149.                     || HasAlgoWaveTableWindowBeenModified(AlgoWaveTableObj->AlgoWaveTableWindow);
  150.             }
  151.          else
  152.             {
  153.                 return AlgoWaveTableObj->DataModified;
  154.             }
  155.     }
  156.  
  157.  
  158. static FunctionParamRec        ArgList[] =
  159.     {
  160.         {"frames",eInteger},
  161.         {"tables",eInteger},
  162.         {"data",eArrayOfFixed}
  163.     };
  164. #define ARGLISTLENGTH (sizeof(ArgList) / sizeof(ArgList[0]))
  165.  
  166.  
  167. /* rebuild the wave table and return True if successful */
  168. MyBoolean                            AlgoWaveTableObjectBuild(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  169.     {
  170.         char*                                Blob;
  171.         PcodeRec*                        FuncCode;
  172.         CompileErrors                Error;
  173.         long                                LineNumber;
  174.         ParamStackRec*            ParamList;
  175.         EvalErrors                    OtherError;
  176.         OpcodeRec*                    ErrorOpcode;
  177.         long                                OffendingInstruction;
  178.         DataTypes                        ReturnType;
  179.         char*                                Buffer;
  180.         largefixedsigned*        Middle;
  181.         long                                Limit;
  182.         long                                Scan;
  183.         long                                NumberOfTablesInIt;
  184.         long                                TotalFrameCount;
  185.  
  186.  
  187.         CheckPtrExistence(AlgoWaveTableObj);
  188.  
  189.         /* make sure we are unbuilt */
  190.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  191.         ERROR(AlgoWaveTableObj->WaveTableData != NIL,PRERR(ForceAbort,
  192.             "AlgoWaveTableObjectBuild:  unbuilt object but it still exists"));
  193.  
  194.         /* bring the world up to date */
  195.         if (!MainWindowMakeUpToDateFunctions(AlgoWaveTableObj->MainWindow))
  196.             {
  197.                 return False;
  198.             }
  199.  
  200.         /* allocate the new wave table thing */
  201.         AlgoWaveTableObj->WaveTableData = NewWaveTableStorage(
  202.             AlgoWaveTableObjectGetNumBits(AlgoWaveTableObj),
  203.             AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj));
  204.         if (AlgoWaveTableObj->WaveTableData == NIL)
  205.             {
  206.              FailurePointNegative1:
  207.                 AlertHalt("There is not enough memory available to compile the algorithmic "
  208.                     "wave table generator function.",NIL);
  209.             }
  210.         for (Scan = 0; Scan < AlgoWaveTableObj->NumTables; Scan += 1)
  211.             {
  212.                 if (!WaveTableStorageAppendEntry(AlgoWaveTableObj->WaveTableData))
  213.                     {
  214.                      FailurePoint0:
  215.                         DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  216.                         goto FailurePointNegative1;
  217.                     }
  218.             }
  219.  
  220.         /* prepare the text blob to be evaluated */
  221.         Blob = AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObj);
  222.         if (Blob == NIL)
  223.             {
  224.              FailurePoint1:
  225.                 goto FailurePoint0;
  226.             }
  227.  
  228.         /* perform compilation */
  229.         Error = CompileSpecialFunction(ArgList,ARGLISTLENGTH,&LineNumber,
  230.             &ReturnType,Blob,&FuncCode);
  231.         ReleasePtr(Blob);
  232.         /* show the error message if there is one */
  233.         if (Error != eCompileNoError)
  234.             {
  235.                 if (!AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj))
  236.                     {
  237.                         AlertHalt("A compile error occurred but there is not enough "
  238.                             "memory available to display the error message.",NIL);
  239.                         return False;
  240.                     }
  241.                 AlgoWaveTableWindowHiliteLine(AlgoWaveTableObj->AlgoWaveTableWindow,LineNumber - 1);
  242.                 AlertHalt("A compile error occurred:  _",GetCompileErrorString(Error));
  243.                 return False;
  244.             }
  245.  
  246.         /* try to evaluate the code */
  247.         ParamList = NewParamStack();
  248.         if (ParamList == NIL)
  249.             {
  250.              SecondFailurePoint1:
  251.                 DisposePcode(FuncCode);
  252.                 AlertHalt("There is not enough memory available to evaluate the algorithmic "
  253.                     "wave table generator function.",NIL);
  254.                 return False;
  255.             }
  256.         /* add a space for the return value */
  257.         if (!AddIntegerToStack(ParamList,0))
  258.             {
  259.              SecondFailurePoint2:
  260.                 DisposeParamStack(ParamList);
  261.                 goto SecondFailurePoint1;
  262.             }
  263.         /* add the special parameters (SymbolStack order MUST be the same */
  264.         /* order as that used for the Parameterlist) */
  265.         if (!AddIntegerToStack(ParamList,AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)))
  266.             {
  267.                 goto SecondFailurePoint2;
  268.             }
  269.         if (!AddIntegerToStack(ParamList,AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)))
  270.             {
  271.                 goto SecondFailurePoint2;
  272.             }
  273.         Buffer = AllocPtrCanFail(0,"degeneratesample");
  274.         if (Buffer == NIL)
  275.             {
  276.                 goto SecondFailurePoint2;
  277.             }
  278.         if (!AddArrayToStack(ParamList,Buffer))
  279.             {
  280.                 ReleasePtr(Buffer);
  281.                 goto SecondFailurePoint2;
  282.             }
  283.  
  284.         /* executing the actual code */
  285.         OtherError = EvaluatePcode(ParamList,FuncCode,
  286.             AlgoWaveTableObj->CodeCenter,&ErrorOpcode,&OffendingInstruction,
  287.             AlgoWaveTableObj->MainWindow,
  288.             &MainWindowGetSampleLeftCopy,&MainWindowGetSampleRightCopy,
  289.             &MainWindowGetSampleMonoCopy,&MainWindowGetWaveTableFrameCount,
  290.             &MainWindowGetWaveTableTableCount,&MainWindowGetWaveTableArray);
  291.         DisposePcode(FuncCode);
  292.         if (OtherError != eEvalNoError)
  293.             {
  294.                 char*                    FuncNameString;
  295.                 FuncCodeRec*    ErrorFunction;
  296.                 MyBoolean            SuccessFlag;
  297.  
  298.                 /* present error message */
  299.                 AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj);
  300.                 SuccessFlag = False;
  301.                 ErrorFunction = GetFunctionFromOpcode(AlgoWaveTableObj->CodeCenter,ErrorOpcode);
  302.                 if (ErrorFunction == NIL)
  303.                     {
  304.                         FuncNameString = StringToBlockCopy("<anonymous>");
  305.                     }
  306.                  else
  307.                     {
  308.                         FuncNameString = CopyPtr(GetFunctionName(ErrorFunction));
  309.                     }
  310.                 if (FuncNameString != NIL)
  311.                     {
  312.                         char*                    Key;
  313.  
  314.                         Key = StringToBlockCopy("_");
  315.                         if (Key != NIL)
  316.                             {
  317.                                 char*                    BaseMessage;
  318.  
  319.                                 BaseMessage = StringFromRaw("Error in function _, instruction _:  _");
  320.                                 if (BaseMessage != NIL)
  321.                                     {
  322.                                         char*                    FixedMessage1;
  323.  
  324.                                         FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
  325.                                         if (FixedMessage1 != NIL)
  326.                                             {
  327.                                                 char*                    NumberStr;
  328.  
  329.                                                 NumberStr = IntegerToString(OffendingInstruction);
  330.                                                 if (NumberStr != NIL)
  331.                                                     {
  332.                                                         char*                    FixedMessage2;
  333.  
  334.                                                         FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
  335.                                                         if (FixedMessage2 != NIL)
  336.                                                             {
  337.                                                                 AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
  338.                                                                 SuccessFlag = True;
  339.                                                                 ReleasePtr(FixedMessage2);
  340.                                                             }
  341.                                                         ReleasePtr(NumberStr);
  342.                                                     }
  343.                                                 ReleasePtr(FixedMessage1);
  344.                                             }
  345.                                         ReleasePtr(BaseMessage);
  346.                                     }
  347.                                 ReleasePtr(Key);
  348.                             }
  349.                         ReleasePtr(FuncNameString);
  350.                     }
  351.                 if (!SuccessFlag)
  352.                     {
  353.                         AlertHalt("There is not enough memory available to show the "
  354.                             "compile error message.",NIL);
  355.                     }
  356.                 DisposeParamStack(ParamList);
  357.                 return False;
  358.             }
  359.  
  360.         /* add the new data */
  361.         Middle = (largefixedsigned*)GetStackArray(ParamList,3);
  362.         if (Middle == NIL)
  363.             {
  364.                 AlertHalt("NIL array returned from algorithmic wave table function.",NIL);
  365.              RebuildFailurePoint1:
  366.                 DisposeParamStack(ParamList);
  367.                 DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  368.                 AlgoWaveTableObj->WaveTableData = NIL;
  369.                 AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj);
  370.                 return False;
  371.             }
  372.         ERROR(PtrSize((char*)Middle) % sizeof(largefixedsigned) != 0,
  373.             PRERR(ForceAbort,"AlgoWaveTableObjectBuild:  array alignment error"));
  374.         NumberOfTablesInIt = AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj);
  375.         TotalFrameCount = AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj);
  376.         if ((PtrSize((char*)Middle) / sizeof(largefixedsigned))
  377.             != NumberOfTablesInIt * TotalFrameCount)
  378.             {
  379.                 AlertHalt("Algorithmic wave table function returned array of wrong size.",NIL);
  380.              RebuildFailurePoint2:
  381.                 goto RebuildFailurePoint1;
  382.             }
  383.         for (Scan = 0; Scan < NumberOfTablesInIt; Scan += 1)
  384.             {
  385.                 long                                Index;
  386.  
  387.                 for (Index = 0; Index < TotalFrameCount; Index += 1)
  388.                     {
  389.                         WaveTableStorageSetFrame(AlgoWaveTableObj->WaveTableData,Scan,Index,
  390.                             Middle[(Scan * TotalFrameCount) + Index]);
  391.                     }
  392.             }
  393.         DisposeParamStack(ParamList);
  394.         AlgoWaveTableObj->NeedsToBeRebuilt = False;
  395.         return True;
  396.     }
  397.  
  398.  
  399. /* remove the wave table data */
  400. void                                    AlgoWaveTableObjectUnbuild(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  401.     {
  402.         CheckPtrExistence(AlgoWaveTableObj);
  403.         if (AlgoWaveTableObj->WaveTableData != NIL)
  404.             {
  405.                 DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
  406.                 AlgoWaveTableObj->WaveTableData = NIL;
  407.             }
  408.     }
  409.  
  410.  
  411. /* rebuild the wave table if it hasn't been built and return success flag */
  412. MyBoolean                            AlgoWaveTableObjectMakeUpToDate(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  413.     {
  414.         CheckPtrExistence(AlgoWaveTableObj);
  415.         if ((AlgoWaveTableObj->WaveTableData == NIL) || (AlgoWaveTableObj->NeedsToBeRebuilt)
  416.             || (AlgoWaveTableObj->AlgoWaveTableWindow != NIL))
  417.             {
  418.                 return AlgoWaveTableObjectBuild(AlgoWaveTableObj);
  419.             }
  420.          else
  421.             {
  422.                 return True;
  423.             }
  424.     }
  425.  
  426.  
  427. /* get a copy of the name of this object */
  428. char*                                    AlgoWaveTableObjectGetNameCopy(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  429.     {
  430.         char*                                NameTemp;
  431.  
  432.         CheckPtrExistence(AlgoWaveTableObj);
  433.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  434.             {
  435.                 NameTemp = AlgoWaveTableWindowGetNameCopy(AlgoWaveTableObj->AlgoWaveTableWindow);
  436.             }
  437.          else
  438.             {
  439.                 NameTemp = CopyPtr(AlgoWaveTableObj->Name);
  440.             }
  441.         if (NameTemp != NIL)
  442.             {
  443.                 SetTag(NameTemp,"AlgoWaveTableNameCopy");
  444.             }
  445.         return NameTemp;
  446.     }
  447.  
  448.  
  449. /* install a new name on the object.  the object becomes owner of the name, so */
  450. /* the caller should not dispose of it. */
  451. void                                    AlgoWaveTableObjectNewName(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  452.                                                 char* Name)
  453.     {
  454.         CheckPtrExistence(AlgoWaveTableObj);
  455.         CheckPtrExistence(Name);
  456.         ReleasePtr(AlgoWaveTableObj->Name);
  457.         SetTag(Name,"AlgoWaveTableName");
  458.         AlgoWaveTableObj->Name = Name;
  459.         AlgoWaveTableObj->DataModified = True;
  460.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  461.         AlgoWaveTableListAlgoWaveTableNameChanged(AlgoWaveTableObj->AlgoWaveTableList,
  462.             AlgoWaveTableObj);
  463.     }
  464.  
  465.  
  466. /* get a copy of the formula that computes the algorithmic wave table */
  467. char*                                    AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  468.     {
  469.         char*                                TextCopy;
  470.  
  471.         CheckPtrExistence(AlgoWaveTableObj);
  472.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  473.             {
  474.                 TextCopy = AlgoWaveTableWindowGetFormulaCopy(AlgoWaveTableObj->AlgoWaveTableWindow);
  475.             }
  476.          else
  477.             {
  478.                 TextCopy = CopyPtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  479.             }
  480.         if (TextCopy != NIL)
  481.             {
  482.                 SetTag(TextCopy,"AlgoWaveTableFormulaCopy");
  483.             }
  484.         return TextCopy;
  485.     }
  486.  
  487.  
  488. /* install a new formula for the algorithmic wave table.  the object becomes the */
  489. /* owner of the memory block so the caller should not dispose of it. */
  490. void                                    AlgoWaveTableObjectNewFormula(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  491.                                                 char* Formula)
  492.     {
  493.         CheckPtrExistence(AlgoWaveTableObj);
  494.         CheckPtrExistence(Formula);
  495.         ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  496.         SetTag(Formula,"AlgoWaveTableFormula");
  497.         AlgoWaveTableObj->AlgoWaveTableFormula = Formula;
  498.         AlgoWaveTableObj->DataModified = True;
  499.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  500.     }
  501.  
  502.  
  503. /* find out how many bits are in each sample frame */
  504. NumBitsType                        AlgoWaveTableObjectGetNumBits(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  505.     {
  506.         CheckPtrExistence(AlgoWaveTableObj);
  507.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  508.             {
  509.                 return AlgoWaveTableWindowGetNumBits(AlgoWaveTableObj->AlgoWaveTableWindow);
  510.             }
  511.          else
  512.             {
  513.                 return AlgoWaveTableObj->NumBits;
  514.             }
  515.     }
  516.  
  517.  
  518. /* install a new number of bits in the object. */
  519. void                                    AlgoWaveTableObjectPutNumBits(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  520.                                                 NumBitsType NewNumBits)
  521.     {
  522.         CheckPtrExistence(AlgoWaveTableObj);
  523.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  524.         ERROR((NewNumBits != eSample16bit) && (NewNumBits != eSample8bit),
  525.             PRERR(ForceAbort,"AlgoWaveTableObjectPutNumBits:  bad value"));
  526.         AlgoWaveTableObj->NumBits = NewNumBits;
  527.         AlgoWaveTableObj->DataModified = True;
  528.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  529.     }
  530.  
  531.  
  532. /* find out how many frames there are per table */
  533. long                                    AlgoWaveTableObjectGetNumTables(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  534.     {
  535.         CheckPtrExistence(AlgoWaveTableObj);
  536.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  537.             {
  538.                 return AlgoWaveTableWindowGetNumTables(AlgoWaveTableObj->AlgoWaveTableWindow);
  539.             }
  540.          else
  541.             {
  542.                 return AlgoWaveTableObj->NumTables;
  543.             }
  544.     }
  545.  
  546.  
  547. /* set the number of tables in the wave table */
  548. void                                    AlgoWaveTableObjectPutNumTables(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  549.                                                 long NumTables)
  550.     {
  551.         CheckPtrExistence(AlgoWaveTableObj);
  552.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  553.         if (NumTables < 0)
  554.             {
  555.                 NumTables = 0;
  556.             }
  557.         AlgoWaveTableObj->NumTables = NumTables;
  558.         AlgoWaveTableObj->DataModified = True;
  559.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  560.     }
  561.  
  562.  
  563. /* get number of frames in each table */
  564. long                                    AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  565.     {
  566.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  567.             {
  568.                 return AlgoWaveTableWindowGetNumFrames(AlgoWaveTableObj->AlgoWaveTableWindow);
  569.             }
  570.          else
  571.             {
  572.                 return AlgoWaveTableObj->NumFrames;
  573.             }
  574.     }
  575.  
  576.  
  577. /* set the number of frames in each table */
  578. void                                    AlgoWaveTableObjectPutNumFrames(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  579.                                                 long NumFrames)
  580.     {
  581.         CheckPtrExistence(AlgoWaveTableObj);
  582.         AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
  583.         AlgoWaveTableObj->NumFrames = NumFrames;
  584.         AlgoWaveTableObj->DataModified = True;
  585.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  586.     }
  587.  
  588.  
  589. /* get a raw slice of data from the wave table.  if the wave table is modified, */
  590. /* this pointer becomes invalid. */
  591. char*                                    AlgoWaveTableObjectGetRawSlice(AlgoWaveTableObjectRec* AlgoWaveTableObj,
  592.                                                 long AlgoWaveTableIndex)
  593.     {
  594.         CheckPtrExistence(AlgoWaveTableObj);
  595.         ERROR((AlgoWaveTableIndex < 0) || (AlgoWaveTableIndex
  596.             > AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)),PRERR(ForceAbort,
  597.             "AlgoWaveTableObjectGetRawSlice:  table index is out of range"));
  598.         return (char*)WaveTableStorageGetTable(AlgoWaveTableObj->WaveTableData,
  599.             AlgoWaveTableIndex);
  600.     }
  601.  
  602.  
  603. /* make the wave table open it's editor window */
  604. MyBoolean                            AlgoWaveTableObjectOpenWindow(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  605.     {
  606.         CheckPtrExistence(AlgoWaveTableObj);
  607.         if (AlgoWaveTableObj->AlgoWaveTableWindow == NIL)
  608.             {
  609.                 AlgoWaveTableObj->AlgoWaveTableWindow
  610.                     = NewAlgoWaveTableWindow(AlgoWaveTableObj->MainWindow,
  611.                     AlgoWaveTableObj,AlgoWaveTableObj->AlgoWaveTableList,
  612.                     AlgoWaveTableObj->SavedWindowXLoc,AlgoWaveTableObj->SavedWindowYLoc,
  613.                     AlgoWaveTableObj->SavedWindowWidth,AlgoWaveTableObj->SavedWindowHeight);
  614.             }
  615.          else
  616.             {
  617.                 AlgoWaveTableWindowBringToTop(AlgoWaveTableObj->AlgoWaveTableWindow);
  618.             }
  619.         return (AlgoWaveTableObj->AlgoWaveTableWindow != NIL);
  620.     }
  621.  
  622.  
  623. /* notify the object that the editor window is closing.  the object should */
  624. /* not take any action. */
  625. void                                    AlgoWaveTableObjectClosingWindowNotify(
  626.                                                 AlgoWaveTableObjectRec* AlgoWaveTableObj,
  627.                                                 short NewX, short NewY, short NewWidth, short NewHeight)
  628.     {
  629.         CheckPtrExistence(AlgoWaveTableObj);
  630.         ERROR(AlgoWaveTableObj->AlgoWaveTableWindow == NIL,PRERR(ForceAbort,
  631.             "AlgoWaveTableObjectClosingWindowNotify:  window not open"));
  632.         AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
  633.         AlgoWaveTableObj->SavedWindowXLoc = NewX;
  634.         AlgoWaveTableObj->SavedWindowYLoc = NewY;
  635.         AlgoWaveTableObj->SavedWindowWidth = NewWidth;
  636.         AlgoWaveTableObj->SavedWindowHeight = NewHeight;
  637.     }
  638.  
  639.  
  640. /* the document's name has changed, so we need to update the window */
  641. void                                    AlgoWaveTableObjectGlobalNameChange(AlgoWaveTableObjectRec*
  642.                                                 AlgoWaveTableObj, char* NewFilename)
  643.     {
  644.         CheckPtrExistence(AlgoWaveTableObj);
  645.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  646.             {
  647.                 AlgoWaveTableWindowGlobalNameChange(AlgoWaveTableObj->AlgoWaveTableWindow,
  648.                     NewFilename);
  649.             }
  650.     }
  651.  
  652.  
  653. /* Algorithmic Wave Table Object Subblock Format: */
  654. /*   1-byte format version number */
  655. /*       should be 1 */
  656. /*   2-byte little endian window X position (signed; origin at top-left corner) */
  657. /*   2-byte little endian window Y position */
  658. /*   2-byte little endian window width */
  659. /*   2-byte little endian window height */
  660. /*   4-byte little endian name length descriptor */
  661. /*   n-byte name string (line feed = 0x0a) */
  662. /*   4-byte little endian formula length descriptor */
  663. /*   n-byte formula string (line feed = 0x0a) */
  664. /*   4-byte little endian number of frames */
  665. /*       should be an integral power of 2 in the interval 2..65536 */
  666. /*   4-byte little endian number of tables */
  667. /*   1-byte number of bits */
  668. /*       should be either 8 or 16 */
  669.  
  670.  
  671. /* read in an object from the file. */
  672. FileLoadingErrors            AlgoWaveTableObjectNewFromFile(AlgoWaveTableObjectRec** ObjectOut,
  673.                                                 struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
  674.                                                 struct MainWindowRec* MainWindow,
  675.                                                 struct AlgoWaveTableListRec* AlgoWaveTableList)
  676.     {
  677.         AlgoWaveTableObjectRec*        AlgoWaveTableObj;
  678.         unsigned char                            UnsignedChar;
  679.         signed long                                SignedLong;
  680.         signed short                            SignedShort;
  681.         FileLoadingErrors                    Error;
  682.  
  683.         CheckPtrExistence(Input);
  684.         CheckPtrExistence(CodeCenter);
  685.         CheckPtrExistence(MainWindow);
  686.         CheckPtrExistence(AlgoWaveTableList);
  687.  
  688.         AlgoWaveTableObj = (AlgoWaveTableObjectRec*)AllocPtrCanFail(
  689.             sizeof(AlgoWaveTableObjectRec),"AlgoWaveTableObjectRec");
  690.         if (AlgoWaveTableObj == NIL)
  691.             {
  692.                 Error = eFileLoadOutOfMemory;
  693.              FailurePoint1:
  694.                 return Error;
  695.             }
  696.  
  697.         /*   1-byte format version number */
  698.         /*       should be 1 */
  699.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  700.             {
  701.                 Error = eFileLoadDiskError;
  702.              FailurePoint2:
  703.                 ReleasePtr((char*)AlgoWaveTableObj);
  704.                 goto FailurePoint1;
  705.             }
  706.         if (UnsignedChar != 1)
  707.             {
  708.                 Error = eFileLoadBadFormat;
  709.              FailurePoint3:
  710.                 goto FailurePoint2;
  711.             }
  712.  
  713.         /*   2-byte little endian window X position (signed; origin at top-left corner) */
  714.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  715.             {
  716.                 Error = eFileLoadDiskError;
  717.              FailurePoint4:
  718.                 goto FailurePoint3;
  719.             }
  720.         AlgoWaveTableObj->SavedWindowXLoc = SignedShort;
  721.  
  722.         /*   2-byte little endian window Y position */
  723.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  724.             {
  725.                 Error = eFileLoadDiskError;
  726.              FailurePoint5:
  727.                 goto FailurePoint4;
  728.             }
  729.         AlgoWaveTableObj->SavedWindowYLoc = SignedShort;
  730.  
  731.         /*   2-byte little endian window width */
  732.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  733.             {
  734.                 Error = eFileLoadDiskError;
  735.              FailurePoint6:
  736.                 goto FailurePoint5;
  737.             }
  738.         AlgoWaveTableObj->SavedWindowWidth = SignedShort;
  739.  
  740.         /*   2-byte little endian window height */
  741.         if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
  742.             {
  743.                 Error = eFileLoadDiskError;
  744.              FailurePoint7:
  745.                 goto FailurePoint6;
  746.             }
  747.         AlgoWaveTableObj->SavedWindowHeight = SignedShort;
  748.  
  749.         /*   4-byte little endian name length descriptor */
  750.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  751.             {
  752.                 Error = eFileLoadDiskError;
  753.              FailurePoint8:
  754.                 goto FailurePoint7;
  755.             }
  756.         if (SignedLong < 0)
  757.             {
  758.                 Error = eFileLoadBadFormat;
  759.              FailurePoint9:
  760.                 goto FailurePoint8;
  761.             }
  762.  
  763.         /*   n-byte name string (line feed = 0x0a) */
  764.         AlgoWaveTableObj->Name = AllocPtrCanFail(SignedLong,"AlgoWaveTableObjectRec:  name");
  765.         if (AlgoWaveTableObj->Name == NIL)
  766.             {
  767.                 Error = eFileLoadOutOfMemory;
  768.              FailurePoint10:
  769.                 goto FailurePoint9;
  770.             }
  771.         if (!ReadBufferedInput(Input,SignedLong,AlgoWaveTableObj->Name))
  772.             {
  773.                 Error = eFileLoadDiskError;
  774.              FailurePoint11:
  775.                 ReleasePtr(AlgoWaveTableObj->Name);
  776.                 goto FailurePoint10;
  777.             }
  778.  
  779.         /*   4-byte little endian formula length descriptor */
  780.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  781.             {
  782.                 Error = eFileLoadDiskError;
  783.              FailurePoint12:
  784.                 goto FailurePoint11;
  785.             }
  786.         if (SignedLong < 0)
  787.             {
  788.                 Error = eFileLoadBadFormat;
  789.              FailurePoint13:
  790.                 goto FailurePoint12;
  791.             }
  792.  
  793.         /*   n-byte formula string (line feed = 0x0a) */
  794.         AlgoWaveTableObj->AlgoWaveTableFormula = AllocPtrCanFail(SignedLong,
  795.             "AlgoWaveTableObjectRec:  formula");
  796.         if (AlgoWaveTableObj->AlgoWaveTableFormula == NIL)
  797.             {
  798.                 Error = eFileLoadOutOfMemory;
  799.              FailurePoint14:
  800.                 goto FailurePoint13;
  801.             }
  802.         if (!ReadBufferedInput(Input,SignedLong,AlgoWaveTableObj->AlgoWaveTableFormula))
  803.             {
  804.                 Error = eFileLoadDiskError;
  805.              FailurePoint15:
  806.                 ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
  807.                 goto FailurePoint14;
  808.             }
  809.  
  810.         /*   4-byte little endian number of frames */
  811.         /*       should be an integral power of 2 between 2 and 65536 */
  812.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  813.             {
  814.                 Error = eFileLoadDiskError;
  815.              FailurePoint16:
  816.                 goto FailurePoint15;
  817.             }
  818.         if ((SignedLong != 2) && (SignedLong != 4) && (SignedLong != 8)
  819.             && (SignedLong != 16) && (SignedLong != 32) && (SignedLong != 64)
  820.             && (SignedLong != 128) && (SignedLong != 256) && (SignedLong != 512)
  821.             && (SignedLong != 1024) && (SignedLong != 2048) && (SignedLong != 4096)
  822.             && (SignedLong != 8192) && (SignedLong != 16384) && (SignedLong != 32768)
  823.             && (SignedLong != 65536))
  824.             {
  825.                 Error = eFileLoadBadFormat;
  826.              FailurePoint17:
  827.                 goto FailurePoint16;
  828.             }
  829.         AlgoWaveTableObj->NumFrames = SignedLong;
  830.  
  831.         /*   4-byte little endian number of tables */
  832.         if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
  833.             {
  834.                 Error = eFileLoadDiskError;
  835.              FailurePoint18:
  836.                 goto FailurePoint17;
  837.             }
  838.         if (SignedLong < 0)
  839.             {
  840.                 Error = eFileLoadBadFormat;
  841.              FailurePoint19:
  842.                 goto FailurePoint18;
  843.             }
  844.         AlgoWaveTableObj->NumTables = SignedLong;
  845.  
  846.         /*   1-byte number of bits */
  847.         /*       should be either 8 or 16 */
  848.         if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
  849.             {
  850.                 Error = eFileLoadDiskError;
  851.              FailurePoint20:
  852.                 goto FailurePoint19;
  853.             }
  854.         if (UnsignedChar == 8)
  855.             {
  856.                 AlgoWaveTableObj->NumBits = eSample8bit;
  857.             }
  858.         else if (UnsignedChar == 16)
  859.             {
  860.                 AlgoWaveTableObj->NumBits = eSample16bit;
  861.             }
  862.         else
  863.             {
  864.                 Error = eFileLoadBadFormat;
  865.              FailurePoint21:
  866.                 goto FailurePoint20;
  867.             }
  868.  
  869.         /* fill in the other fields */
  870.         AlgoWaveTableObj->DataModified = False;
  871.         AlgoWaveTableObj->NeedsToBeRebuilt = True;
  872.         AlgoWaveTableObj->WaveTableData = NIL;
  873.         AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
  874.         AlgoWaveTableObj->CodeCenter = CodeCenter;
  875.         AlgoWaveTableObj->MainWindow = MainWindow;
  876.         AlgoWaveTableObj->AlgoWaveTableList = AlgoWaveTableList;
  877.  
  878.         *ObjectOut = AlgoWaveTableObj;
  879.         return eFileLoadNoError;
  880.     }
  881.  
  882.  
  883. /* write the object out to the file. */
  884. FileLoadingErrors            AlgoWaveTableObjectWriteDataOut(
  885.                                                 AlgoWaveTableObjectRec* AlgoWaveTableObj,
  886.                                                 struct BufferedOutputRec* Output)
  887.     {
  888.         char*                                StringTemp;
  889.  
  890.         CheckPtrExistence(AlgoWaveTableObj);
  891.         CheckPtrExistence(Output);
  892.  
  893.         /*   1-byte format version number */
  894.         /*       should be 1 */
  895.         if (!WriteBufferedUnsignedChar(Output,1))
  896.             {
  897.                 return eFileLoadDiskError;
  898.             }
  899.  
  900.         /*   2-byte little endian window X position (signed; origin at top-left corner) */
  901.         /* note that if the window is open when the file is saved, then the most recent */
  902.         /* coordinates of the window will not be used. */
  903.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowXLoc))
  904.             {
  905.                 return eFileLoadDiskError;
  906.             }
  907.  
  908.         /*   2-byte little endian window Y position */
  909.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowYLoc))
  910.             {
  911.                 return eFileLoadDiskError;
  912.             }
  913.  
  914.         /*   2-byte little endian window width */
  915.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowWidth))
  916.             {
  917.                 return eFileLoadDiskError;
  918.             }
  919.  
  920.         /*   2-byte little endian window height */
  921.         if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowHeight))
  922.             {
  923.                 return eFileLoadDiskError;
  924.             }
  925.  
  926.         /*   4-byte little endian name length descriptor */
  927.         StringTemp = AlgoWaveTableObjectGetNameCopy(AlgoWaveTableObj);
  928.         if (StringTemp == NIL)
  929.             {
  930.                 return eFileLoadOutOfMemory;
  931.             }
  932.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  933.             {
  934.                 ReleasePtr(StringTemp);
  935.                 return eFileLoadDiskError;
  936.             }
  937.  
  938.         /*   n-byte name string (line feed = 0x0a) */
  939.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  940.             {
  941.                 ReleasePtr(StringTemp);
  942.                 return eFileLoadDiskError;
  943.             }
  944.         ReleasePtr(StringTemp);
  945.  
  946.         /*   4-byte little endian formula length descriptor */
  947.         StringTemp = AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObj);
  948.         if (StringTemp == NIL)
  949.             {
  950.                 return eFileLoadOutOfMemory;
  951.             }
  952.         if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
  953.             {
  954.                 ReleasePtr(StringTemp);
  955.                 return eFileLoadDiskError;
  956.             }
  957.  
  958.         /*   n-byte formula string (line feed = 0x0a) */
  959.         if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
  960.             {
  961.                 ReleasePtr(StringTemp);
  962.                 return eFileLoadDiskError;
  963.             }
  964.         ReleasePtr(StringTemp);
  965.  
  966.         /*   4-byte little endian number of frames */
  967.         /*       should be an integral power of 2 between 2 and 65536 */
  968.         if (!WriteBufferedSignedLongLittleEndian(Output,
  969.             AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)))
  970.             {
  971.                 return eFileLoadDiskError;
  972.             }
  973.  
  974.         /*   4-byte little endian number of tables */
  975.         if (!WriteBufferedSignedLongLittleEndian(Output,
  976.             AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)))
  977.             {
  978.                 return eFileLoadDiskError;
  979.             }
  980.  
  981.         /*   1-byte number of bits */
  982.         /*       should be either 8 or 16 */
  983.         switch (AlgoWaveTableObjectGetNumBits(AlgoWaveTableObj))
  984.             {
  985.                 default:
  986.                     EXECUTE(PRERR(ForceAbort,"AlgoWaveTableObjectWriteDataOut:  bad num bits"));
  987.                     break;
  988.                 case eSample8bit:
  989.                     if (!WriteBufferedUnsignedChar(Output,8))
  990.                         {
  991.                             return eFileLoadDiskError;
  992.                         }
  993.                     break;
  994.                 case eSample16bit:
  995.                     if (!WriteBufferedUnsignedChar(Output,16))
  996.                         {
  997.                             return eFileLoadDiskError;
  998.                         }
  999.                     break;
  1000.             }
  1001.  
  1002.         return eFileLoadNoError;
  1003.     }
  1004.  
  1005.  
  1006. /* mark algorithmic wave table object as saved */
  1007. void                                    AlgoWaveTableObjectMarkAsSaved(AlgoWaveTableObjectRec* AlgoWaveTableObj)
  1008.     {
  1009.         CheckPtrExistence(AlgoWaveTableObj);
  1010.         if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
  1011.             {
  1012.                 AlgoWaveTableWindowWritebackModifiedData(AlgoWaveTableObj->AlgoWaveTableWindow);
  1013.             }
  1014.         AlgoWaveTableObj->DataModified = False;
  1015.     }
  1016.